/**
 * @file      sht30_module.c
 * @brief     messure  temperature and humidity
 *
 * @author    Hi_SPARK Team
 * @date      2021/7/21
 * @version   1.0
 */

#include "sht30_module.h"
#include "hisignalling_protocol.h"

#define SHT30_TASK_SIZE       (2304)

#define SHT30_TASK_PRIO       (26)

hi_u32 g_sht30_id;

static hi_void sht30_io_init(hi_void)
{
    //hi_io_set_func(HI_IO_NAME_GPIO_10, HI_IO_FUNC_GPIO_10_I2C0_SDA);/* SHT30 温湿度 */
    //hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_I2C0_SCL);/* SHT30  温湿度*/
    hi_i2c_init(HI_I2C_IDX_0,400000); /* baudrate: 100000 */
    hi_i2c_set_baudrate(HI_I2C_IDX_0 , 400000);
}

static hi_void sht30_init(hi_void)
{
    hi_u32 status;
    sht30_io_init();
    hi_i2c_data sht30_i2c_data = { 0 };
    hi_u8 send_data[2] = { 0x23,0x34 };
    sht30_i2c_data.send_buf = send_data;
    sht30_i2c_data.send_len = 2;
    status = hi_i2c_write(HI_I2C_IDX_0, (SHT30_Addr<<1)|0x00, &sht30_i2c_data);
    if (status != HI_ERR_SUCCESS) {
        printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
        return status;
    }
}

hi_void sht30_reset(hi_void)
{
    hi_u32 status;
    hi_i2c_data sht30_i2c_data = { 0 };
    hi_u8 send_data[2] = { 0x30,0xA2 };
    sht30_i2c_data.send_buf = send_data;
    sht30_i2c_data.send_len = 2;
    status = hi_i2c_write(HI_I2C_IDX_0, (SHT30_Addr<<1)|0x00, &sht30_i2c_data);
    if (status != HI_ERR_SUCCESS) {
        printf("===== Error: I2C write status = 0x%x! =====\r\n", status);
        return status;
    }
}

static hi_u8 sht30_checkcrc(hi_u8 data[], hi_u8 numOfBytes, hi_u8 checkSum)
{
    hi_u8 crc = 0xFF;
    hi_u8 bit = 0;
    hi_u8 byteCtr ;
    const hi_u16 POLYNOMIAL = 0x131;
    for(byteCtr = 0; byteCtr < numOfBytes; ++byteCtr)
    {
        crc ^= (data[byteCtr]);
        for ( bit = 8; bit > 0; --bit)
        {
            if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
            else crc = (crc << 1);
        }
    }

    if(crc != checkSum)
        return 1;
    else
        return 0;
}

static hi_float sht30_calctemperature(hi_u16 u16sT)
{
    hi_float temperature = 0;            // variable for result

    u16sT &= ~0x0003;           // clear bits [1..0] (status bits)
    //-- calculate temperature [℃] --
    temperature = (175 * (hi_float)u16sT / 65535 - 45); //T = -45 + 175 * rawValue / (2^16-1)
    
    return temperature;
}

static hi_float sht30_calcrh(hi_u16 u16sRH)
{
    hi_float humidityRH = 0;              // variable for result
    
    u16sRH &= ~0x0003;          // clear bits [1..0] (status bits)
    //-- calculate relative humidity [%RH] --
    humidityRH = (100 * (hi_float)u16sRH / 65535);  // RH = rawValue / (2^16-1) * 10
    
    return humidityRH;
}

static hi_void sht30_read_data(SHT30_DATA *pstsht30_data)
{
    hi_float temperature,humidity;
    hi_u8  data[3];    //data array for checksum verification
    hi_u16 dat,tmp;
    hi_u8 SHT3X_Data_Buffer[6];                                                                       //byte 0,1 is temperature byte 4,5 is humidity

    hi_i2c_data sht30_i2c_data = { 0 };
    hi_u8 send_data[2] = { 0xE0,0x00};

    hi_u32 ret;

    sht30_i2c_data.send_buf = send_data;
    sht30_i2c_data.send_len = 2;
    sht30_i2c_data.receive_buf = SHT3X_Data_Buffer;
    sht30_i2c_data.receive_len = 6;                                                                                      //Read bh1750 sensor data 
    hi_i2c_writeread(HI_I2C_IDX_0, (SHT30_Addr<<1)|0x00, &sht30_i2c_data);

    //    /* check tem */
    data[0] = SHT3X_Data_Buffer[0];
    data[1] = SHT3X_Data_Buffer[1];
    data[2] = SHT3X_Data_Buffer[2];

    tmp=sht30_checkcrc(data, 2, data[2]);
    if( !tmp ) /* value is ture */
    {
       dat = ((hi_u16)data[0] << 8) | data[1];
       temperature = sht30_calctemperature(dat);
       printf("Temperature =  %.2f\r\n",temperature);
       ret = hi_mux_pend(g_mux_id,100);
        if (ret == HI_ERR_SUCCESS){
            hisignalling_type_msg(PLUG_COMMON_HISIGNALING_TEMPERATURE, temperature);
            hi_mux_post(g_mux_id);
        }
    }

    //    /* check humidity */
    data[0] = SHT3X_Data_Buffer[3];
    data[1] = SHT3X_Data_Buffer[4];
    data[2] = SHT3X_Data_Buffer[5];

    tmp=sht30_checkcrc(data, 2, data[2]);
    if( !tmp ) /* value is ture */
    {
       dat = ((hi_u16)data[0] << 8) | data[1];
       humidity = sht30_calcrh( dat );
       printf("Humidity =  %.2f\r\n",humidity);
       ret = hi_mux_pend(g_mux_id,100);
        if (ret == HI_ERR_SUCCESS){
            hisignalling_type_msg(PLUG_COMMON_HISIGNALING_HUMIDITY, humidity);
            hi_mux_post(g_mux_id);
        }
    }
    
    pstsht30_data->temperature = temperature;
    pstsht30_data->humidity = humidity;
    
}

static hi_void sht30_thread(hi_void)
{
    hi_u32 ret;
    SHT30_DATA sht30_data;
    sht30_init();
    for(;;) 
    {
        sht30_read_data(&sht30_data);
//        printf("sht30_data.humidity = %.2f\r\n",sht30_data.humidity);
//        printf("sht30_data.temperature = %.2f\r\n",sht30_data.temperature);
        hi_sleep(1000);
    }
    /*Delete task*/
    ret = hi_task_delete(g_sht30_id);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to sht30_thread\r\n");
    }

}



hi_u32 sht30_task(hi_void)
{
    hi_u32 ret;
    hi_task_attr sht30_attr = {0};
    
    sht30_attr.stack_size = SHT30_TASK_SIZE;//Task stack memory
    sht30_attr.task_prio = SHT30_TASK_PRIO;//The task priority ranges from 0 to 31. Tasks 0 to 10 should not be used. The SDK has been used. The higher the value, the lower the priority
    sht30_attr.task_name = (hi_char*)"sht30  control";//Task name
	//Create task
    ret = hi_task_create(&g_sht30_id, &sht30_attr, sht30_thread, HI_NULL);
    if (ret != HI_ERR_SUCCESS) {
        printf("Failed to create sht30_thread\r\n");
        return HI_ERR_FAILURE;
    }
    return HI_ERR_SUCCESS;
}



